﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

namespace MyTestProject {

    public class TestVertexBuffer {

        [Fact]
        public void TestConstructor () {
            var vbuf = new VertexBuffer ();

            Assert.Equal (0, vbuf.VertexCount);
            Assert.Equal (true, vbuf.Mutable);
            Assert.Equal (null, vbuf.Positions (null));
            Assert.Equal (null, vbuf.Normals (null));
            Assert.Equal (null, vbuf.Colors (null));
            Assert.Equal (null, vbuf.PointSizes (null));
            Assert.Equal (null, vbuf.BoneIndices);
            Assert.Equal (null, vbuf.BoneWeights);
            Assert.Equal (null, vbuf.TexCoords (0, null));
            Assert.Equal (null, vbuf.TexCoords (1, null));
            Assert.Equal (0, vbuf.AttributeCount);
            Assert.Equal (0, vbuf.AttributeNames.Length);
            Assert.Equal (0xffffffff, vbuf.DefaultColor);
            Assert.Equal (1.0f, vbuf.DefaultPointSize);
        }

        [Fact]
        public void TestGetVertexCount () {
            var vbuf = new VertexBuffer ();
            var normals = new VertexArray (4, 3, ArrayType.Byte);

            vbuf.SetNormals (normals);

            Assert.Equal (4, vbuf.VertexCount);
        }

        [Fact]
        public void TestCommit () {
            var vbuf = new VertexBuffer ();
            vbuf.Commit ();

            Assert.Equal (false, vbuf.Mutable);
        }

        /**
         * Attributeを追加するテスト
         * */
        [Fact]
        public void TestSetAttribute1 () {
            var vbuf  = new VertexBuffer ();
            var varry = new VertexArray (4, 3, ArrayType.Short);
            vbuf.SetAttribute ("Miyafuji Yoshika", varry, true, true);
            vbuf.SetAttribute ("Lynette Bishop", varry, true, true);
            vbuf.SetAttribute ("Perrine H. Clostermann", varry, true, true);

             Assert.Equal (3, vbuf.AttributeCount);
            Assert.Equal ("Miyafuji Yoshika", vbuf.AttributeNames[0]);
            Assert.Equal ("Lynette Bishop", vbuf.AttributeNames[1]);
            Assert.Equal ("Perrine H. Clostermann", vbuf.AttributeNames[2]);
        }


        /**
         * Attributeのデフォルト値をセットするテスト
         * */
        [Fact]
        public void TestSetAttribute2 () {
            var vbuf = new VertexBuffer ();
            var attr = new VertexArray (4, 3, ArrayType.Short);
            vbuf.SetAttribute ("Miyafuji Yoshika", attr, false, true);
            vbuf.SetAttribute ("Miyafuji Yoshika", 1929, 8, 18, 15);

            var signedNormalized = new bool[2];
            var defaultValue     = new float[4];

            var expected         = new float[4] { 1929, 8, 18, 15 };

            Assert.Equal (attr, vbuf.Attribute ("Miyafuji Yoshika", signedNormalized, defaultValue));
            Assert.Equal (false, signedNormalized[0]);
            Assert.Equal (true, signedNormalized[1]);
            Assert.Equal (expected, defaultValue);
        }


        [Fact]
        public void TestSetBoneInfluences () {
            var vbuf = new VertexBuffer ();
            var boneIndices = new VertexArray (6, 2, ArrayType.Byte);
            var boneWeights = new VertexArray (6, 2, ArrayType.Float);

            vbuf.SetBoneInfluences (boneIndices, boneWeights);

            Assert.Equal (boneIndices, vbuf.BoneIndices);
            Assert.Equal (boneWeights, vbuf.BoneWeights);
        }


        [Fact]
        public void TestSetPositions () {
            var vbuf      = new VertexBuffer ();
            var positions = new VertexArray (4, 3, ArrayType.Float);
            vbuf.SetPositions (positions, 99.0f, new float[] { 1, 2, 3 });

            var scaleBias = new float[4];
            var expected  = new float[] { 99.0f, 1, 2, 3 };

            Assert.Equal (positions, vbuf.Positions (scaleBias));
            Assert.Equal (expected, scaleBias);
        }


        [Fact]
        public void TestSetNormals () {
            var vbuf = new VertexBuffer ();
            var normals = new VertexArray (3, 3, ArrayType.Short);

            vbuf.SetNormals (normals);

            var scaleBias = new float[4];
            var expected  = new float[] { 2 / 65535.0f, 1 / 65535.0f, 1 / 65535.0f, 1 / 65535.0f };

            Assert.Equal (normals, vbuf.Normals (scaleBias));
            Assert.Equal (expected, scaleBias);
        }

        [Fact]
        public void TestSetColors () {
            var vbuf   = new VertexBuffer ();
            var colors = new VertexArray (4, 3, ArrayType.Byte);
            vbuf.SetColors (colors);

            var scaleBias = new float[4];
            var expected  = new float[] { 1 / 255.0f, 0, 0, 0 };

            Assert.Equal (colors, vbuf.Colors (scaleBias));
            Assert.Equal (expected, scaleBias);
        }

        [Fact]
        public void TestSetPointSizes () {
            var vbuf       = new VertexBuffer ();
            var pointSizes = new VertexArray (4, 1, ArrayType.Fixed);
            vbuf.SetPointSizes (pointSizes);

            var scaleBias = new float[2];
            var expected  = new float[] { 1 / 65536.0f, 0 };

            Assert.Equal (pointSizes, vbuf.PointSizes (scaleBias));
            Assert.Equal (expected, scaleBias);
        }



        [Fact]
        public void TestSetTexCoords () {
            var vbuf      = new VertexBuffer ();
            var texCoords = new VertexArray (4, 3, ArrayType.Float);

            vbuf.SetTexCoords (0, texCoords, 99.0f, new float[] { 1, 2, 3 });
            vbuf.SetTexCoords (1, texCoords, 99.0f, new float[] { 1, 2, 3 });

            var scaleBias = new float[4];
            var expected  = new float[] { 99.0f, 1, 2, 3 };

            Assert.Equal (texCoords, vbuf.TexCoords (0, scaleBias));
            Assert.Equal (expected, scaleBias);

            Assert.Equal (texCoords, vbuf.TexCoords (1, scaleBias));
            Assert.Equal (expected, scaleBias);
        }


        [Fact]
        public void TestSetDefaultColor () {
            var vbuf = new VertexBuffer ();
            vbuf.DefaultColor = 0x87654321;

            Assert.Equal (0x87654321, vbuf.DefaultColor);
        }


        [Fact]
        public void TestSetDefaultPointSize () {
            var vbuf = new VertexBuffer ();
            vbuf.DefaultPointSize = 0x12345678;

            Assert.Equal (0x12345678, vbuf.DefaultPointSize);
        }

        [Fact]
        public void TestReferences () {
            var vbuf = new VertexBuffer ();

            var positions   = new VertexArray (4, 3, ArrayType.Float);
            var normals     = new VertexArray (4, 3, ArrayType.Short);
            var colors      = new VertexArray (4, 3, ArrayType.Byte);
            var texCoords   = new VertexArray (4, 3, ArrayType.Float);
            var pointSizes  = new VertexArray (4, 1, ArrayType.Fixed);
            var boneIndices = new VertexArray (4, 2, ArrayType.Byte);
            var boneWeights = new VertexArray (4, 2, ArrayType.Float);
            var attr        = new VertexArray (4, 3, ArrayType.Short);

            vbuf.SetPositions      (positions, 1.0f, new float[] { 0, 0, 0 });
            vbuf.SetNormals        (normals);
            vbuf.SetColors         (colors);
            vbuf.SetPointSizes     (pointSizes);
            vbuf.SetTexCoords      (0, texCoords, 1.0f, new float[] { 0, 0, 0 });
            vbuf.SetTexCoords      (1, texCoords, 1.0f, new float[] { 0, 0, 0 });
            vbuf.SetBoneInfluences (boneIndices, boneWeights);
            vbuf.SetAttribute      ("Miyafuji Yoshika", attr, false, true);

            var refs = vbuf.References;

            Assert.Equal (9, refs.Length);
            Assert.Equal (positions, refs[0]);
            Assert.Equal (normals, refs[1]);
            Assert.Equal (colors, refs[2]);
            Assert.Equal (pointSizes, refs[3]);
            Assert.Equal (boneIndices, refs[4]);
            Assert.Equal (boneWeights, refs[5]);
            Assert.Equal (texCoords, refs[6]);
            Assert.Equal (texCoords, refs[7]);
            Assert.Equal (attr, refs[8]);
        }

        [Fact]
        public void TestDuplicate () {
            var vbuf = new VertexBuffer ();
            var positions = new VertexArray (4, 3, ArrayType.Float);
            var normals = new VertexArray (4, 3, ArrayType.Byte);
            var colors = new VertexArray (4, 3, ArrayType.Byte);
            var pointSizes = new VertexArray (4, 1, ArrayType.Fixed);
            var texCoords = new VertexArray (4, 3, ArrayType.Float);
            var varry = new VertexArray (4, 3, ArrayType.Short);
            var boneIndices = new VertexArray (6, 2, ArrayType.Byte);
            var boneWeights = new VertexArray (6, 2, ArrayType.Float);

            vbuf.SetPositions (positions, 99.0f, new float[] { 1, 2, 3 });
            vbuf.SetNormals (normals);
            vbuf.SetColors (colors);
            vbuf.SetPointSizes (pointSizes);
            vbuf.SetTexCoords (0, texCoords, 99.0f, new float[] { 1, 2, 3 });
            vbuf.SetTexCoords (1, texCoords, 99.0f, new float[] { 1, 2, 3 });
            vbuf.DefaultColor = 0x87654321;
            vbuf.DefaultPointSize = 0x12345678;
                        vbuf.SetBoneInfluences (boneIndices, boneWeights);
            vbuf.SetAttribute ("Miyafuji Yoshika", varry, true, true);
            vbuf.SetAttribute ("Miyafuji Yoshika", 1929, 8, 18, 15);
            vbuf.Commit ();
            vbuf.UserID = 100;

            var dup = (VertexBuffer)vbuf.Duplicate();

            Assert.Equal (vbuf.VertexCount, vbuf.VertexCount);
            Assert.Equal (vbuf.Mutable, vbuf.Mutable);
            Assert.Equal (vbuf.Positions (null), vbuf.Positions (null));
            Assert.Equal (vbuf.Normals (null), vbuf.Normals (null));
            Assert.Equal (vbuf.Colors (null), vbuf.Colors (null));
            Assert.Equal (vbuf.PointSizes (null), vbuf.PointSizes (null));
            Assert.Equal (vbuf.BoneIndices, vbuf.BoneIndices);
            Assert.Equal (vbuf.BoneWeights, vbuf.BoneWeights);
            Assert.Equal (vbuf.TexCoords (0, null), vbuf.TexCoords (0, null));
            Assert.Equal (vbuf.TexCoords (1, null), vbuf.TexCoords (1, null));
            Assert.Equal (vbuf.AttributeCount, vbuf.AttributeCount);
            Assert.Equal (vbuf.AttributeNames.Length, vbuf.AttributeNames.Length);
            Assert.Equal (vbuf.DefaultColor, vbuf.DefaultColor);
            Assert.Equal (vbuf.DefaultPointSize, vbuf.DefaultPointSize);
            Assert.Equal(vbuf.UserID, vbuf.UserID);

        }

    }
}
